﻿using System;
using System.Web.Mvc;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using WebCalendar.Models;
using WebCalendar.Models.Authorization;
using WebCalendar.Models.DTOs;
using WebMatrix.WebData;

namespace WebCalendar.Controllers
{
    
    public class CalendarController : Controller
    {
        //
        // GET: /Calendar/

        private WebCalendarContext db = new WebCalendarContext();

        public ActionResult Index(int id, int? year, int? month )
        {
            var date = DateTime.Now;
            if (year.HasValue && month.HasValue) date = new DateTime((int)year, (int)month, 1);
            return View(new CalendarIndexDTO { CalendarID = id, Month = date.Month, Year = date.Year });
        }

        [Authorize]
        public ActionResult List()
        {
            var user = WebCalendarUser.GetUserProfile(db);
            //var ownCalendars = user.CalendarRoles.OfType<OwnerRole>().Select(m => m.Calendar).ToList();

            var model = new ManageIndexDTO 
            { OwnCalendars = user.CalendarRoles.OfType<OwnerRole>().Select(m => m.Calendar).ToList(),
              EditableCalendars = user.CalendarRoles.OfType<EditorRole>().Select(m => m.Calendar).ToList(),
              MemberCalendars = user.CalendarRoles.OfType<MemberRole>().Select(m => m.Calendar).ToList()
            };
            return View(model);
        }
        /// <summary>
        /// A paraméterben kapott felhasználó Publikus naptárjai
        /// </summary>
        /// <param name="id">felhasználónév</param>
        /// <returns></returns>
        public ActionResult Public(string id)
        {
            var user = db.UserProfiles.Include("CalendarRoles").Include("CalendarRoles.Calendar").FirstOrDefault(m => m.UserName == id);
            if (user == null)
                return HttpNotFound();
            var ownCalendars = user.CalendarRoles.OfType<OwnerRole>().Where(m=> m.Calendar.IsPublic).Select(m => m.Calendar).ToList();

            var model = new CalendarPublicDTO
            {
                Calendars = ownCalendars,
                User = user
            };
            return View(model);
        }

        [HttpPost]
        [Authorize]
        public ActionResult Publish(int id)
        {
            var user = WebCalendarUser.GetUserProfile(db);
            var ownCalendars = user.CalendarRoles.OfType<OwnerRole>().Select(m => m.Calendar).ToList();
            var calendar = ownCalendars.FirstOrDefault(m => m.ID == id);
            // csak azt tudja publisholni, amelyiknél owner a felhasználó
            if(calendar == null)
                return View("~/Views/Calendar/NoAccess.cshtml");
            calendar.IsPublic = true;
            db.SaveChanges();
            return RedirectToAction("List");
        }

        [HttpPost]
        [Authorize]
        public ActionResult Unpublish(int id)
        {
            var user = WebCalendarUser.GetUserProfile(db);
            var ownCalendars = user.CalendarRoles.OfType<OwnerRole>().Select(m => m.Calendar).ToList();
            var calendar = ownCalendars.FirstOrDefault(m => m.ID == id);
            // csak azt tudja publisholni, amelyiknél owner a felhasználó
            if (calendar == null)
                return View("~/Views/Calendar/NoAccess.cshtml");
            calendar.IsPublic = false;
            db.SaveChanges();
            return RedirectToAction("List");
        }

        [HttpPost]
        public ActionResult AddEntry(int id, EntryData entry)
        {
            var calendar = db.Calendars.Find(id);
            if (String.IsNullOrEmpty(entry.StartDateString))
            {
                entry.IsAllDay = true;
            }
            else
            {
                entry.StartDate = DateTime.Parse(entry.StartDateString);
                if (!String.IsNullOrEmpty(entry.EndDateString))
                {
                    entry.EndDate = DateTime.Parse(entry.EndDateString);
                }
            }
            var dbEnty = new Entry { Title = entry.Title, Description = entry.Description, StartDate = entry.StartDate, EndDate = entry.EndDate, IsAllDay = entry.IsAllDay };
            db.Entries.Add(dbEnty);
            var category = db.Categories.Find(entry.CategoryID);
            var personalEntry = new PersonalEntry { EntryBase = dbEnty, Category = category };
            db.PersonalEntries.Add(personalEntry);
            var entryFilter = new EntryFilter { Entry = personalEntry, Calendar = calendar, Visible = true };
            db.EntryFilters.Add(entryFilter);
            if (db.SaveChanges() > 0)
            {
                return Json(new { success = true, ID = personalEntry.ID });
            }
            return Json(new { success = false, message= "nothing changed in the datebase" });
        }

        public ActionResult UpdateEntry(int id, EntryData entry)
        {
            var calendar = db.Calendars.Find(id);
            if (String.IsNullOrEmpty(entry.StartDateString))
            {
                entry.IsAllDay = true;
            }
            else
            {
                entry.StartDate = DateTime.Parse(entry.StartDateString);
                if (!String.IsNullOrEmpty(entry.EndDateString))
                {
                    entry.EndDate = DateTime.Parse(entry.EndDateString);
                }
            }
            var personalEnty = db.PersonalEntries.Include("EntryBase").Include("Category").FirstOrDefault(m=> m.ID == entry.ID);
            if(personalEnty.Category.ID != entry.ID)
            {
                var category = db.Categories.Find(entry.CategoryID);
                personalEnty.Category = category;
            }
            var dbEntry = personalEnty.EntryBase;
            dbEntry.Description = entry.Description;
            dbEntry.EndDate = entry.EndDate;
            dbEntry.StartDate = entry.StartDate;
            dbEntry.IsAllDay = entry.IsAllDay;
            dbEntry.Title = entry.Title;
            
            if (db.SaveChanges() > 0)
            {
                return Json(new { success = true, ID = dbEntry.ID });
            }
            return Json(new { success = false, message = "nothing changed in the datebase" });
        }

        [Authorize]
        public ActionResult DeleteEntry(int id)
        {
            //var user = WebCalendarUser.GetUserProfile(db);
            var entryFiltersToRemove = db.EntryFilters.Where(m=> m.Entry.ID == id).ToList();

            foreach (var item in entryFiltersToRemove)
            {
		        db.EntryFilters.Remove(item);
            }

            var personalEntry = db.PersonalEntries.Include("EntryBase").FirstOrDefault(m=> m.ID == id);
            var entryBase = personalEntry.EntryBase;
            db.PersonalEntries.Remove(personalEntry);
            db.Entries.Remove(entryBase);
            db.SaveChanges();
            return Json(new { success = true });
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id">Calendar Id</param>
        /// <returns></returns>
        
        public ActionResult GetEntries(int id, int? year, int? month)
        {
            if (!month.HasValue) month = DateTime.Now.Month;
            if (!year.HasValue) year = DateTime.Now.Year;
            var categories = new List<Category>();
            var user = WebCalendarUser.GetUserProfile(db);
            var calendar = db.Calendars.Include("EntryFilters").Include("EntryFilters.Entry").Include("EntryFilters.Entry.EntryBase").FirstOrDefault(m=> m.ID == id );

            if (calendar.IsPublic && user == null)
            {
                categories = new List<Category>(){
                    new Category{ Color = "#9A81B5", Name = "Default", ID = -1}
                };

                var monthEntries = calendar.EntryFilters.Where(m => m.Visible && m.Entry.EntryBase.StartDate.HasValue && m.Entry.EntryBase.StartDate.Value.Year == year && m.Entry.EntryBase.StartDate.Value.Month == month);
                var list = monthEntries.Select(m => m.Entry).OrderBy(m => m.EntryBase.StartDate).ToList();
                return Json(
                    new
                    {
                        Categories = categories.Select(m => new Category { ID = m.ID, Name = m.Name, Color = m.Color }),
                        Entries = list.Select(m => new EntryData
                        {
                            Category = categories.FirstOrDefault(),
                            CategoryID = -1,
                            Description = m.EntryBase.Description,
                            Title = m.EntryBase.Title,
                            StartDate = m.EntryBase.StartDate,
                            EndDate = m.EntryBase.EndDate,
                            IsAllDay = m.EntryBase.IsAllDay,
                            ID = m.ID,
                            RecurringDays = m.EntryBase.RecurringDays
                        })
                    }, JsonRequestBehavior.AllowGet);
            }
            else
            {
                categories = user.Categories.ToList();


                var monthEntries = calendar.EntryFilters.Where(m => m.Visible && m.Entry.EntryBase.StartDate.HasValue && m.Entry.EntryBase.StartDate.Value.Month == month && categories.Contains(m.Entry.Category));
                var list = monthEntries.Select(m => m.Entry).OrderBy(m => m.EntryBase.StartDate).ToList();
                return Json(
                    new
                    {
                        Categories = categories.Select(m => new Category { ID = m.ID, Name = m.Name, Color = m.Color }),
                        Entries = list.Select(m => new EntryData
                        {
                            Category = new Category { ID = m.Category.ID, Color = m.Category.Color, Name = m.Category.Name },
                            CategoryID = m.Category.ID,
                            Description = m.EntryBase.Description,
                            Title = m.EntryBase.Title,
                            StartDate = m.EntryBase.StartDate,
                            EndDate = m.EntryBase.EndDate,
                            IsAllDay = m.EntryBase.IsAllDay,
                            ID = m.ID,
                            RecurringDays = m.EntryBase.RecurringDays
                        })
                    }, JsonRequestBehavior.AllowGet);

            }

            
        }

        public ActionResult Day(int? year, int? month, int? day)
        {
            var date = DateTime.Now;
            if (year.HasValue && month.HasValue && day.HasValue) date = new DateTime((int)year, (int)month, (int)day);
            var model = new MonthDTO
            {
                DateToShow = date
            };
            return View(model);
        }
        public ActionResult Week(int? year, int? month, int? day)
        {
            var date = DateTime.Now;
            if (year.HasValue && month.HasValue && day.HasValue) date = new DateTime((int)year, (int)month, (int)day);
            var model = new MonthDTO
            {
                DateToShow = date
            };
            return View(model);
        }
        public ActionResult Month(int id, int? year, int? month)
        {
            var date = DateTime.Now;
            if (year.HasValue && month.HasValue) date = new DateTime((int)year, (int)month, 1);

            var calendar = db.Calendars.Find(id);

            if (calendar == null)
                return HttpNotFound();

            var user = WebCalendarUser.GetUserProfile(db);
            if ( !calendar.IsPublic && user == null){
                return View("~/Views/Calendar/NoAccess.cshtml");
            }

            // be van jelentkezve, és roleon keresztük hozzáférhet a naptárhoz
            if (user != null)
            {
                var role = user.CalendarRoles.FirstOrDefault(m => m.Calendar.ID == id);
                if (role != null)
                {
                    var model = new CalendarIndexDTO { CalendarID = calendar.ID, Year = date.Year, Month = date.Month, DateToShow = date, Calendar = calendar, Role = role };
                    return View(model);
                }
            }



            // Publikus
            if (calendar.IsPublic)
            {
                var model = new CalendarIndexDTO { CalendarID = calendar.ID, Year = date.Year, Month = date.Month, DateToShow = date, Calendar = calendar, Role = null };
                return View(model);
            }

            return HttpNotFound();
        }
    }
}
